TOOL.Category    = "Conna's Tools"
TOOL.Name        = "#Perimeter Turret Tool"
TOOL.Command     = nil
TOOL.ConfigName  = ""

TOOL.ClientConVar["Model"] = "models/props_junk/PopCan01a.mdl"
TOOL.ClientConVar["Description"] = ""
TOOL.ClientConVar["Type"] = "SMG"
TOOL.ClientConVar["Radius"] = "512"

// Turrets

PerimeterTurret      = {}
PerimeterTurret.List = {}

// Add

function PerimeterTurret.Add(ID, Function)
	PerimeterTurret.List[ID] = Function
end

// Turrets

local Files = file.FindInLua("Turrets/*.lua")

for K, V in pairs(Files) do
	if (SERVER) then
		AddCSLuaFile("Turrets/"..V)
	end
	
	include("Turrets/"..V)
end

// Register

cleanup.Register("perimeterturrets")

// Console

CreateConVar("sbox_maxperimeterturrets", 1, FCVAR_NOTIFY)

// Client

if (CLIENT) then
	// Tool
	
	language.Add("Tool_perimeterturret_name", "Perimeter Turret Tool")
	language.Add("Tool_perimeterturret_desc", "Perimeter Turret which shoots objects near it")
	language.Add("Tool_perimeterturret_0", "Left click to spawn a Perimeter Turret")
	
	// Other
	
	language.Add("Undone_perimeterturret", "Undone Perimeter Turret")
	language.Add("SBoxLimit_perimeterturrets", "You've hit the Perimeter Turrets limit!")
	language.Add("Cleanup_perimeterturrets", "Perimeter Turrets")
	language.Add("Cleaned_perimeterturrets", "Cleaned up all Perimeter Turrets")
end

// Message

function TOOL:Message(Text)
	if SERVER then
		self:GetOwner():SendLua("GAMEMODE:AddNotify('"..Text.."', NOTIFY_GENERIC, 10)")
		self:GetOwner():SendLua("surface.PlaySound('ambient/water/drip"..math.random(1, 4)..".wav')")
	end
end

// Left click

function TOOL:LeftClick(Trace)
	if(CLIENT) then
		return true
	end
	
	// Locals
	
	local Player = self:GetOwner()

	local Radius = self:GetClientNumber("Radius")
	local Type   = self:GetClientInfo("Type")
	local Description = self:GetClientInfo("Description")
	local Model = self:GetClientInfo("Model")
	
	// Check
	
	if (!PerimeterTurret.List[Type]) then
		self:Message("The Perimeter Turret "..Type.." does not exist!")
		
		return false
	end
	
	// Keep it nice and whole
	
	Radius = math.Clamp(Radius, 0, 512)
	
	if (Trace.Entity and Trace.Entity:IsValid() and Trace.Entity:GetClass() == "gmod_perimeterturret") then
		local Entity = Trace.Entity
		
		// Merge
		
		local Table = {
			Description = Description
		}
		
		table.Merge(Entity:GetTable(), Table)
		
		// Other
		
		Entity:GetTable():SetEntityType(Type)
		Entity:GetTable():SetEntityRadius(Radius)
		Entity:GetTable():SetEntityLabel(Description)
		
		self:Message("Properties changed for Perimeter Turret Turret!")
		
		return true
	end
	
	local Ang = Trace.HitNormal:Angle()
	
	Ang.pitch = Ang.pitch + 90

	local Turret = CreatePerimeterTurret(Player, Ang, Trace.HitPos, Type, Model, Radius, Description)
	
	if not (Turret) then return false end
	
	local Minimum = Turret:OBBMins()
	
	Turret:SetPos(Trace.HitPos - Trace.HitNormal * Minimum.z)
	
	undo.Create("perimeterturret")
	
	if (Trace.Entity and not Trace.Entity:IsWorld()) then
		local Weld = constraint.Weld(Turret, Trace.Entity, 0, Trace.PhysicsBone, 0, true, true)
		
		undo.AddEntity(Weld)
		
		Player:AddCleanup("perimeterturrets", Weld)
		
		Turret:GetPhysicsObject():EnableCollisions(false)
	end
	
	undo.AddEntity(Turret)
	
	undo.SetPlayer(Player)
	
	undo.Finish()
	
	Player:AddCount("perimeterturrets", Turret)
	
	Player:AddCleanup("perimeterturrets", Turret)
	
	self:Message("Perimeter Turret Turret has been created!")
	
	return true, Turret
end

// Make it

if (SERVER) then
	function CreatePerimeterTurret(Player, Ang, Pos, Type, Model, Radius, Description, Nocollide, Vel, Avel, Frozen)
		if (!Player:CheckLimit("perimeterturrets")) then return false end
		
		local Turret = ents.Create("gmod_perimeterturret")
		
		Turret:SetModel(Model)
		Turret:SetAngles(Ang)
		Turret:SetPos(Pos)
		Turret:Spawn()
		
		// Merge
		
		local Table = {
			Description = Description,
			Type = Type,
			Radius = Radius
		}
		
		table.Merge(Turret:GetTable(), Table)
		
		// Set the entities owner
		
		Turret:GetTable():SetPlayer(Player)
		
		// Other
		
		Turret:GetTable():SetEntityType(Type)
		Turret:GetTable():SetEntityRadius(Radius)
		Turret:GetTable():SetEntityLabel(Description)
		
		if Frozen then Turret:GetPhysicsObject():EnableMotion(false) end
		
		if Nocollide then Turret:GetPhysicsObject():EnableCollisions(false) end
		
		return Turret
	end
	
	duplicator.RegisterEntityClass("gmod_perimeterturret", CreatePerimeterTurret, "Ang", "Pos", "Type", "Model", "Radius", "Description", "Nocollide", "Vel", "Avel", "Frozen")
end

// Control panel

function TOOL.BuildCPanel(Panel)
	Panel:AddControl("Header", {Text = "#Tool_perimeterturret_name", Description = "#Tool_perimeterturret_desc"})

	local Combo = {}
	
	Combo.Label = "Weapon"
	
	Combo.Options = {}
	
	for K, V in pairs(PerimeterTurret.List) do
		Combo.Options[K] = {perimeterturret_Type = K}
	end
	
	Panel:AddControl("ComboBox", Combo)
	
	Panel:AddControl("Slider", {Label = "Radius", Type = "Integer", Min = 0, Max = 512, Command = "perimeterturret_Radius"})

	Panel:AddControl("TextBox", {Label = "Description", MaxLength = "100", Command = "perimeterturret_Description"})
end

// Ghost

function TOOL:UpdateGhostPerimeterTurret(Entity, Player)
	if (!Entity) then return end
	
	if (!Entity:IsValid()) then return end

	local TR = utilx.GetPlayerTrace(Player, Player:GetCursorAimVector())
	
	local Trace = util.TraceLine(TR)
	
	if (!Trace.Hit) then return end
	
	if (Trace.Entity && Trace.Entity:GetClass() == "gmod_perimeterturret" || Trace.Entity:IsPlayer()) then
		Entity:SetNoDraw(true)
		
		return
	end
	
	local Ang = Trace.HitNormal:Angle()
	
	Ang.pitch = Ang.pitch + 90
	
	local Minimum = Entity:OBBMins()
	
	Entity:SetPos(Trace.HitPos - Trace.HitNormal * Minimum.z)
	
	Entity:SetAngles(Ang)
	
	Entity:SetNoDraw(false)
end

// Think

function TOOL:Think()
	if (self:GetOwner() and self:GetOwner():IsPlayer()) then
		if (!self.GhostEntity || !self.GhostEntity:IsValid() || self.GhostEntity:GetModel() != self:GetClientInfo("Model")) then
			self:MakeGhostEntity(self:GetClientInfo("Model"), Vector(0, 0, 0), Angle(0, 0, 0) )
		end
		
		self:UpdateGhostPerimeterTurret(self.GhostEntity, self:GetOwner())
	end
end